home *** CD-ROM | disk | FTP | other *** search
- #include <osbind.h>
- #define TT 0xffff /* A time-saver for some arrays. */
-
- int intin[64],intout[64],contrl[12],ptsin[64],ptsout[64],c,gl_apid;
- int array[104*52],pxy[10],pal[16],handle,offset,i,j,*base;
- long ncells; /* # of cells in the matrix. */
- int yoff[52];
- int tcolumn[52],bcolumn[52],change[52];
-
- int palette[16] = { /* Color definitions for "rainbow" */
- 0x000,0x700,0x730,0x750,0x770,0x470,0x070,0x075,0x077,0x057,0x027,
- 0x007,0x507,0x707,0x704,0x777 };
-
- int curform[37] = { /* Box cursor mouse form definition */
- 2,2,1,0,1,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0xf800,0x8800,0x8800,0x8800,0xf800,0,0,0,0,0,0,0,0,0,0,0 };
-
- /* Continue and Live tables (for faster color cycling) */
- int cotab[16]={0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15};
- int litab[16]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15};
-
- /* Top and Bottom arrays for fast processing later on */
- int topcol[52],botcol[52];
-
- /* Tables for fast plot routine */
- int bits[4]={0xe000,0x0e00,0x00e0,0x000e};
- int ebit[4]={0x0fff,0xf0ff,0xff0f,0xfff0};
- int bit0[16]={0,TT,0,TT,0,TT,0,TT,0,TT,0,TT,0,TT,0,TT};
- int bit1[16]={0,0,TT,TT,0,0,TT,TT,0,0,TT,TT,0,0,TT,TT};
- int bit2[16]={0,0,0,0,TT,TT,TT,TT,0,0,0,0,TT,TT,TT,TT};
- int bit3[16]={0,0,0,0,0,0,0,0,TT,TT,TT,TT,TT,TT,TT,TT};
-
- /* Do one generation on the grid. */
- do_grid()
- {
- register int x,y,xo,n,*aptr,*point;
- int o,t,b,tcol,bcol,ch;
- for (x=1; x<49; ++x)
- {
- if (change[x] == 1) /* Only scan columns that need to be checked. */
- {
- t=tcolumn[x]; b=bcolumn[x];
- tcol=0; bcol=0; ch=0;
- xo=x+52-offset;
- for (y=t; y<=b; ++y)
- {
- aptr=&(array[x+offset-1+(y-1)*104]); /* Count neighbors... */
- asm { /* ... with a fast 68000 routine. */
- move.w #0,n
- move.w (aptr),D0
- beq l01
- addq.w #1,n
- l01: move.w 2(aptr),D0
- beq l02
- addq.w #1,n
- l02: move.w 4(aptr),D0
- beq l10
- addq.w #1,n
- l10: move.w 208(aptr),D0
- beq l12
- addq.w #1,n
- l12: move.w 212(aptr),D0
- beq l20
- addq.w #1,n
- l20: move.w 416(aptr),D0
- beq l21
- addq.w #1,n
- l21: move.w 418(aptr),D0
- beq l22
- addq.w #1,n
- l22: move.w 420(aptr),D0
- beq ldo
- addq.w #1,n
- ldo:
- }
- o=array[x+offset+yoff[y]]; /* Get old cell value. */
- point=&array[xo+yoff[y]]; /* Get address of new cell value. */
- if (n == 2) /* 2 neigbors? */
- *point = cotab[o]; /* Yes, continue present state. */
- if (n == 3) /* 3 neighbors? */
- *point = litab[o]; /* Yes, bring to life or keep alive. */
- if ((n<2) || (n>3)) /* Anything else? */
- *point = 0; /* Yes, this cell is DEAD. */
- if (*point != o) /* Did it change? */
- { if (*point && (!o)) /* Yes, update cell count. */
- ++ncells;
- if (! *point)
- --ncells;
- ++ch;
- plot(x-1,y-1,*point); /* Plot new point. */
- if (tcol == 0) /* Update top and bottom of column. */
- tcol=topcol[y];
- bcol=botcol[y];
- }
- }
- if (x > 1)
- { if ((tcolumn[x-1] < tcol) && (change[x-1] == 1))
- tcol=tcolumn[x-1];
- if ((bcolumn[x-1] > bcol) && (change[x-1] == 1))
- bcol=bcolumn[x-1];
- }
- if (! tcol)
- ++tcol;
- if (bcol>50)
- --bcol;
- bcolumn[x]=bcol;
- tcolumn[x]=tcol;
- if (tcol < tcolumn[x-1])
- tcolumn[x-1]=tcol;
- if (bcol > bcolumn[x-1])
- bcolumn[x-1]=bcol;
- if (ch != 0)
- { change[x-1]=1;
- change[x]=1;
- change[x+1]=1;
- }
- else
- change[x]=0;
- }
- }
- }
-
- /* Initialize array and let user draw a pattern. Kludgy, but it works. */
- edit_array()
- {
- int x,y,mx,my,butn;
- clear_rect();
- v_gtext(handle,204,150,"Left button to");
- v_gtext(handle,207,156,"toggle cells.");
- v_gtext(handle,204,165,"Right button to");
- v_gtext(handle,207,171,"begin generation.");
- butn=1;
- while (butn & 1)
- graf_mkstate(&x,&x,&butn,&x);
- v_show_c(handle,0);
- butn=0;
- while (! (butn & 2)) /* Wait for right button */
- { graf_mkstate(&mx,&my,&butn,&x);
- if (butn & 1) /* Left button is pressed */
- { int n;
- x=mx/4+1; y=my/4+1;
- if (x<49) /* In the workspace? */
- { n=(! array[x+offset+yoff[y]]);
- changcell(x,y,n);
- while (butn & 1)
- { graf_mkstate(&mx,&my,&butn,&y);
- changcell(mx/4+1,my/4+1,n);
- }
- }
- }
- }
- while (butn&0x0002) /* Wait for button to be released */
- graf_mkstate(&mx,&my,&butn,&x);
- }
-
- /* Change cell state to ON or OFF (color 1). */
- changcell(x,y,state)
- int x,y,state;
- {
- int *st2;
- if (x>48)
- return(0);
- st2=&array[x+offset+yoff[y]];
- if ((*st2&&state)||((!*st2)&&(!state)))
- return(0);
- *st2=state;
- v_hide_c(handle);
- plot(x-1,y-1,state);
- if (state)
- ++ncells;
- else
- --ncells;
- printn(270,128,ncells);
- v_show_c(handle,0);
- }
-
- /* Tie everything together. */
- main()
- {
- int work_in[11],work_out[57],butns,key,dummy,x,y;
- long gen;
- appl_init();
- if ((int)Getrez())
- { form_alert(1,"[2][Life! requires| |LOW RESOLUTION!][Okay...]");
- exit(0);
- }
- for (i=0; i<16; ++i) /* Save user's colors. */
- pal[i]=(int)Setcolor(i,-1);
- Setpallete(palette); /* Install rainbow colors. */
- base=(int *)Physbase(); /* Get screen address. */
- for (i=0; i<10; work_in[i]=1, ++i);
- work_in[10]=2;
- v_opnvwk(work_in,&handle,work_out);
- v_hide_c(handle);
- v_clrwk(handle);
- vsf_interior(handle,1);
- vsc_form(handle,curform);
- title();
- offset=0; gen=0; ncells=0;
- for (x=0; x<52; ++x)
- { yoff[x]=x*104;
- for (y=0; y<52; ++y)
- { array[x+yoff[y]]=0;
- array[x+52+yoff[y]]=0;
- }
- }
-
- edit:
- edit_array();
-
- dogens:
- for (x=0; x<52; ++x)
- { tcolumn[x]=1; bcolumn[x]=50;
- change[x]=1;
- topcol[x]=x-1; botcol[x]=x+1;
- }
- change[0] = 0; change[49] = 0;
- topcol[1] = 1; topcol[50] = 50;
- clear_rect();
- v_gtext(handle,204,150,"Left button to");
- v_gtext(handle,207,156,"edit cells");
- v_gtext(handle,204,165,"Right button to");
- v_gtext(handle,207,171,"exit program");
- v_gtext(handle,204,180,"Alternate to pause");
- v_hide_c(handle);
- while (1)
- { ++gen;
- printn(270,120,gen);
- printn(270,128,ncells);
- do_grid();
- offset = 52-offset;
- graf_mkstate(&dummy,&dummy,&butns,&key);
- if (butns == 1)
- goto edit;
- if (butns == 2)
- break;
- while (key==8)
- graf_mkstate(&dummy,&dummy,&dummy,&key);
- }
- xbios(6,pal);
- appl_exit();
- exit(0);
- }
-
- /* Plot all the junk on the right side of the screen. */
- title()
- {
- vsf_color(handle,14); /* ST color 11 */
- pxy[0]=194; pxy[1]=0;
- pxy[2]=194; pxy[3]=199;
- pxy[4]=319; pxy[5]=199;
- pxy[6]=319; pxy[7]=0;
- pxy[8]=194; pxy[9]=0;
- v_pline(handle,5,pxy);
- vst_color(handle,9); /* ST color 8 */
- vst_height(handle,28,&i,&i,&i,&i);
- vst_effects(handle,16);
- v_gtext(handle,214,30,"Life!");
- vst_height(handle,6,&i,&i,&i,&i);
- vst_effects(handle,0);
- vst_color(handle,2); /* ST color 1 */
- v_gtext(handle,208,60,"Steven Grimm");
- vst_color(handle,4); /* ST color 4 */
- vst_height(handle,4,&i,&i,&i,&i);
- v_gtext(handle,250,49,"by");
- v_gtext(handle,207,88,"ANALOG Computing");
- vst_color(handle,7); /* ST color 5 */
- v_gtext(handle,204,120,"Generation:");
- v_gtext(handle,234,128,"Cells:");
- }
-
- /* Clear a rectangle in the lower right corner of the screen to print
- instructions. */
- clear_rect()
- {
- pxy[0]=195; pxy[1]=140;
- pxy[2]=318; pxy[3]=198;
- vsf_color(handle,0);
- vr_recfl(handle,pxy);
- }
-
- /* Print generation number next to "Generation:". */
- printn(x,y,num)
- int x,y;
- long num;
- {
- long i;
- char c[2],pnum=0;
- if (! num) /* Special handling for no cells */
- { v_gtext(handle,x,y,"NONE");
- return(0);
- }
- c[1]=0;
- for (i=10000000; i>0; i /= 10) /* Print one power of 10 at a time */
- { if ((num/i) || (x>270)) /* Need to print a digit? */
- { c[0]=(num/i)+48; /* What do we want to print? */
- v_gtext(handle,x,y,c); /* Put the digit to the screen */
- num -= (i*(num/i)); /* Subtract it from the main number */
- x += 6; /* Move the "cursor" */
- ++pnum;
- }
- }
- c[0]=32;
- while (pnum<8) /* Pad the rest of the space with blanks */
- { ++pnum;
- v_gtext(handle,x,y,c);
- x += 6;
- }
- }
-
- /* Special plot routine. */
- plot(x,y,color)
- int x,y,color;
- {
- static int b0,b1,b2,b3,*screen,xbit;
- auto int *eptr;
- screen=base;
- screen += (y*320);
- screen += (x & 0xfffc);
- x = x & 0x0003;
- xbit = bits[x];
- b0 = bit0[color] & xbit;
- b1 = bit1[color] & xbit;
- b2 = bit2[color] & xbit;
- b3 = bit3[color] & xbit;
- eptr=ebit+x;
- asm {
- movea.l screen(A4),A1
- movea.l eptr(A6),A0
- move.w (A1),D0
- and.w (A0),D0
- or.w b0(A4),D0
- move.w D0,(A1)
- move.w 2(A1),D1
- and.w (A0),D1
- or.w b1(A4),D1
- move.w D1,2(A1)
- move.w 4(A1),D2
- and.w (A0),D2
- or.w b2(A4),D2
- move.w D2,4(A1)
- move.w 6(A1),D3
- and.w (A0),D3
- or.w b3(A4),D3
- move.w D3,6(A1)
- adda.l #160,A1
- move.w D0,(A1)
- move.w D1,2(A1)
- move.w D2,4(A1)
- move.w D3,6(A1)
- adda.l #160,A1
- move.w D0,(A1)
- move.w D1,2(A1)
- move.w D2,4(A1)
- move.w D3,6(A1)
- }
- }
-
- /* Null routines to trick the Megamax linker into not including the
- (unnecessary) file I/O stuff */
- fopen()
- { }
- fclose()
- { }
- fread()
- { }
- fwrite()
- { }
- fseek()
- { }
-